home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxcode / jmp / modplay.c < prev    next >
C/C++ Source or Header  |  1994-01-29  |  5KB  |  174 lines

  1. #include <dos.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <malloc.h>
  5. #include "modplay.h"
  6. #include "device.h"
  7.  
  8. void    fillbuffer(uchar *);
  9. void    worknote(note *, channel *);
  10.  
  11. module    song;
  12. char *    sampledata[31];
  13. note *    patterndata[64];
  14. char    buffer[2][2500];
  15.  
  16. uint    playrate;
  17. uint    tablepos;
  18. uint    patternpos;
  19. ulong    patternticks;
  20. ulong    patternticksaim;
  21. ulong    sampleticksconst;
  22. channel    channels[4];
  23.  
  24. int
  25. modload(char * filename)
  26. {
  27.     uint    i, j, max;
  28.     uchar    a, b, c;
  29.     sample    *sptr;
  30.     FILE    *fp;
  31.  
  32.     if ((fp = fopen(filename, "rb")) == NULL) return 0;
  33.     if (fread(&(song.title), 1, 1084, fp) != 1084) return 0;
  34.     if (memcmp(&(song.signature), "M.K.", 4) != 0 &&
  35.         memcmp(&(song.signature), "FLT4", 4) != 0 &&
  36.         memcmp(&(song.signature), "FLT8", 4) != 0) {
  37.         memcpy(&(song.signature), "M.K.", 4);
  38.         memcpy(&(song.length), &(song.samples[15]), 130);
  39.         memset(&(song.samples[15]), 0, 480);
  40.         if (fseek(fp, 600L, SEEK_SET) != 0) return 0;
  41.     }
  42.     for (i = max = 0; i < 128; i++)
  43.         while (max <= song.patterntable[i]) {
  44.             if ((patterndata[max]=malloc(1024))==NULL) return 0;
  45.             if (fread(patterndata[max++],1024,1,fp)!=1) return 0;
  46.         }
  47.     for (i = 0, sptr = song.samples; i < 31; i++, sptr++) {
  48.         _AX = sptr->length; asm {xchg ah, al}; sptr->length = _AX * 2;
  49.         _AX = sptr->reppnt; asm {xchg ah, al}; sptr->reppnt = _AX * 2;
  50.         _AX = sptr->replen; asm {xchg ah, al}; sptr->replen = _AX * 2;
  51.         if (sptr->length == 0) continue;
  52.         if ((sampledata[i] = malloc(sptr->length)) == NULL) return 0;
  53.         fread(sampledata[i], sptr->length, 1, fp);
  54.         if (sptr->replen + sptr->reppnt > sptr->length)
  55.             sptr->replen = sptr->length - sptr->reppnt;
  56.         for (max = 0; max < sptr->length; max++)
  57.             sampledata[i][max] ^= 0x80;
  58.     }
  59.     return 1;
  60. }
  61.  
  62. int
  63. modinit(int frequency)
  64. {
  65.     if ((sbinit(0x220, 7, 1) == 0)) return 0;
  66.     if ((playrate = sbrate(frequency)) == 0) return 0;
  67.     return playrate;
  68. }
  69.  
  70. int
  71. modplay(void)
  72. {
  73.     tablepos = 0;
  74.     patternpos = 0;
  75.     patternticks = 6L * playrate / 51 + 1;
  76.     patternticksaim = 6L * playrate / 51;
  77.     sampleticksconst = 3445744UL / playrate;
  78.     channels[0].volume = 0; channels[0].period = 448;
  79.     channels[1].volume = 0; channels[1].period = 448;
  80.     channels[2].volume = 0; channels[2].period = 448;
  81.     channels[3].volume = 0; channels[3].period = 448;
  82.     fillbuffer(buffer[0]);
  83.     fillbuffer(buffer[1]);
  84.     sbdblbuf(buffer[0], 2500, buffer[1], 2500);
  85.     return 1;
  86. }
  87.  
  88. int
  89. modpoll(void)
  90. {
  91.     if (tablepos > song.length) {
  92.         return 1;
  93.     } else if (bufoverlap) {
  94.         return 2;
  95.     } else if (bufempty[bufplaying^1]) {
  96.         bufempty[bufplaying^1] = 0;
  97.         fillbuffer(buffer[bufplaying^1]);
  98.         return 0;
  99.     } else
  100.         return 0;
  101. }
  102.  
  103. int
  104. modstop(void)
  105. {
  106.     sbstop();
  107.     return 0;
  108. }
  109.  
  110. void
  111. fillbuffer(uchar * buffer)
  112. {
  113.     uint    i, j, k, l;
  114.     note    *nptr;
  115.     channel *cptr;
  116.  
  117.     for (i = 0; i < 2500; i++) {
  118.         if (patternticks++ > patternticksaim) {
  119.             nptr = patterndata[song.patterntable[tablepos]];
  120.             nptr = nptr + patternpos;
  121.             cptr = channels;
  122.             patternpos += 4;
  123.             patternticks = 0;
  124.             worknote(nptr+0, cptr+0);
  125.             worknote(nptr+1, cptr+1);
  126.             worknote(nptr+2, cptr+2);
  127.             worknote(nptr+3, cptr+3);
  128.             if (patternpos == 256) {
  129.                 tablepos++;
  130.                 patternpos = 0;
  131.             }
  132.         }
  133.         for (j = l = 0, cptr = channels; j < 4; j++, cptr++) {
  134.             k = sampleticksconst * cptr->ticks++ / cptr->period;
  135.             if (k > cptr->length) {
  136.                 cptr->sampdata += cptr->reppnt;
  137.                 cptr->length = cptr->replen;
  138.                 cptr->reppnt = 0;
  139.                 cptr->ticks = 0;
  140.                 l += cptr->sampdata[0] * cptr->volume;
  141.             } else
  142.                 l += cptr->sampdata[k] * cptr->volume;
  143.         }
  144.         buffer[i] = l / 256;
  145.     }
  146. }
  147.  
  148. void
  149. worknote(note * nptr, channel * cptr)
  150. {
  151.     uint    sample, period, effect;
  152.  
  153.     sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4);
  154.     period = ((nptr->sampperiod & 0xF) << 8) | nptr->period;
  155.     effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect;
  156.     if (period != 0) {
  157.         if (sample != 0) cptr->sampnum = --sample;
  158.         cptr->sampdata = sampledata[cptr->sampnum];
  159.         cptr->length = song.samples[cptr->sampnum].length;
  160.         cptr->reppnt = song.samples[cptr->sampnum].reppnt;
  161.         cptr->replen = song.samples[cptr->sampnum].replen;
  162.         cptr->volume = song.samples[cptr->sampnum].volume;
  163.         cptr->period = period;
  164.         cptr->ticks = 0;
  165.     }
  166.     switch (effect >> 8) {
  167.         case 0xF: patternticksaim=(long)(effect&0xFF)*playrate/51;break;
  168.         case 0xD: patternpos = (effect & 0xFF) * 4; tablepos++; break;
  169.         case 0xC: cptr->volume = (effect & 0xFF); break;
  170.         case 0xB: tablepos = (effect & 0xFF); break;
  171.         case 0x9: cptr->sampdata += (effect & 0xFF) * 256; break;
  172.     }
  173. }
  174.